<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <title>WebGL Texture Mipmap</title>
</head>
<body>
<div style="text-align: center">
   SE<canvas id="canvas" width="128" height="128"></canvas>VO
</div>
<script id="vertexshader" type="x-shader">
   attribute vec2 aVertexPosition;
   attribute vec2 aTextureCoord;

   varying vec2 vTextureCoord;

   uniform float uTime;

   void main() {
      vTextureCoord = aTextureCoord;
      mat4 rotMat = mat4(sin(uTime), 0.0, 0.0, 0.0,
                         0.0, sin(uTime), 0.0, 0.0,
                         0.0, 0.0, 1.0, 0.0,
                         0.0, 0.0, 0.0, 1.0);

      gl_Position = rotMat * vec4(aVertexPosition, 0.0, 1.0);
   }
</script>
<script id="fragmentshader" type="x-shader">
   precision mediump float;
   varying vec2 vTextureCoord;

   uniform sampler2D uSampler;

   void main() {
      gl_FragColor = texture2D(uSampler, vTextureCoord);
   }
</script>
<script type="text/javascript">

   var canvas;
   function initWebGL()
   {
      canvas = document.getElementById("canvas");
      var gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
      if (!gl) return null; // can't initialize WebGL
      return gl;
   }

   var gl = initWebGL();

   // Setup Shaders:
   var v = document.getElementById("vertexshader").firstChild.nodeValue;
   var f = document.getElementById("fragmentshader").firstChild.nodeValue;

   var vs = gl.createShader(gl.VERTEX_SHADER);
   gl.shaderSource(vs, v);
   gl.compileShader(vs);

   if (!gl.getShaderParameter(vs, gl.COMPILE_STATUS)) {
       console.log(gl.getShaderInfoLog(vs));
   }

   var fs = gl.createShader(gl.FRAGMENT_SHADER);
   gl.shaderSource(fs, f);
   gl.compileShader(fs);

   if (!gl.getShaderParameter(fs, gl.COMPILE_STATUS)) {
       console.log(gl.getShaderInfoLog(fs));
   }

   program = gl.createProgram();
   gl.attachShader(program, vs);
   gl.attachShader(program, fs);
   gl.linkProgram(program);

    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
       console.log(gl.getProgramInfoLog(program));
    }

   gl.useProgram(program);

   program.aVertexPosition = gl.getAttribLocation(program, "aVertexPosition");
   gl.enableVertexAttribArray(program.aVertexPosition);

   program.aTextureCoord = gl.getAttribLocation(program, "aTextureCoord");
   gl.enableVertexAttribArray(program.aTextureCoord);

   var rustTexture = gl.createTexture();
   var rustImage = new Image();
   rustImage.onload = function() { handleTextureLoaded(rustImage, rustTexture); }
   rustImage.src = "rust-power-of-two.png";


   // Setup Geometry
   var vertices = new Float32Array([
       -1.0, -1.0,
       -1.0,  1.0,
        1.0, -1.0,
        1.0,  1.0  // Square-Coordinates
   ]);

   var textureCoords = new Float32Array([
       0.0, 0.0,
       0.0, 1.0,
       1.0, 0.0,
       1.0, 1.0
   ]);

   vbuffer = gl.createBuffer();
   gl.bindBuffer(gl.ARRAY_BUFFER, vbuffer);
   gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

   uvbuffer = gl.createBuffer();
   gl.bindBuffer(gl.ARRAY_BUFFER, uvbuffer);
   gl.bufferData(gl.ARRAY_BUFFER, textureCoords, gl.STATIC_DRAW);

   itemSize = 2; // we have 2 coordinates (x,y)
   numItems = vertices.length / itemSize; // number of vertices

   // Viewport
   gl.viewport(0, 0, canvas.width, canvas.height);

   program.time = gl.getUniformLocation(program, "uTime");

   var start_time = new Date().getTime() / 1000;

   setInterval(function () {
     gl.clearColor(1, 0, 0, 1);
     gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
     // Draw

     gl.bindBuffer(gl.ARRAY_BUFFER, vbuffer);
     gl.vertexAttribPointer(program.aVertexPosition, itemSize, gl.FLOAT, false, 0, 0);

     gl.bindBuffer(gl.ARRAY_BUFFER, uvbuffer);
     gl.vertexAttribPointer(program.aTextureCoord, 2, gl.FLOAT, false, 0, 0);

     gl.activeTexture(gl.TEXTURE0);
     gl.bindTexture(gl.TEXTURE_2D, rustTexture);
     var dt = new Date().getTime() / 1000 - start_time;
     gl.uniform1f(program.time, dt);

     gl.drawArrays(gl.TRIANGLE_STRIP, 0, numItems);
   }, 15);

   function handleTextureLoaded(image, texture) {
     console.log("handleTextureLoaded, image = " + image);
     gl.bindTexture(gl.TEXTURE_2D, texture);
     gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
     gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
     gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
     gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
     gl.generateMipmap(gl.TEXTURE_2D);
     gl.bindTexture(gl.TEXTURE_2D, null);
   }

</script>
</body>
</html>
